package com.potevio.simulator.encode;

//import com.haoxy.client.common.GetHexMessage;
//import com.haoxy.client.common.MsgBean;
//import com.haoxy.client.init.ApplicationStartQuartzJobListener;
//import com.haoxy.client.strategy.CommandContext;
//import com.haoxy.client.strategy.MsgFieldTypeStrategy;
//import com.haoxy.client.util.HexUtil;
import com.potevio.simulator.common.CommonFlag;
import com.potevio.simulator.common.GetHexMessage;
import com.potevio.simulator.common.MsgBean;
import com.potevio.simulator.config.MsgTypeConst;
import com.potevio.simulator.heart.HeartbeatClient;
import com.potevio.simulator.init.ApplicationStartQuartzJobListener;
import com.potevio.simulator.strategy.CommandContext;
import com.potevio.simulator.strategy.MsgFieldTypeStrategy;
import com.potevio.simulator.util.HexUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * Created by haoxy on 2018/10/17.
 * E-mail:hxyHelloWorld@163.com
 * github:https://github.com/haoxiaoyong1014
 * 客户端编码器
 */
public class MsgEncode extends MessageToByteEncoder {
    private final static Logger LOGGER = LoggerFactory.getLogger(MessageToByteEncoder.class);

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Object obj, ByteBuf byteBuf) throws Exception {
        // 编码
        String hexString = object2HexStr(obj);
        HexUtil.parse(hexString, "1");
        // 将16进制字符串转为数组
        byteBuf.writeBytes(HexUtil.hexString2Bytes(hexString));
    }

    public static void main(String[] args) {
        String beginHex = "FAF52780AB3A000000000101010000000000000000";
        String endHex = "630066000101003F011E00";
        // 电池总电压1
        int num = HexUtil.makeRandom(210f, 245f, 0).intValue();
        String dczdy = HexUtil.random2HexAndReverse(num);
        // 电池总电流1
        num = HexUtil.makeRandom(110f, 90f, 0).intValue() + 3200;
        String dczdl = HexUtil.random2HexAndReverse(num);;
        // 最高单体电压1
        num = HexUtil.makeRandom(210f, 245f, 0).intValue();
        String zgdtdy = HexUtil.random2HexAndReverse(num);
        // 最低单体电压1
        String zddtdy = "0000";
        // 温度测量点最高值1
        num = HexUtil.makeRandom(40f, 50f, 0).intValue();
        String wdcldzgz = HexUtil.int2Hex(num);
        // 温度测量点最低值1
        num = HexUtil.makeRandom(40f, 50f, 0).intValue();
        String wdcldzdz = HexUtil.int2Hex(num);
        String resultHex = beginHex + dczdy + dczdl + zgdtdy + zddtdy + wdcldzgz + wdcldzdz + endHex;
        System.out.println(resultHex);
        System.out.println(resultHex.substring(10, resultHex.length()));
//        String checkSumDomain = HexUtil.getCheckSumDomain(resultHex.substring(11, resultHex.length()));
//        System.out.println(checkSumDomain);
    }

    /**
     * 数据对象转为16进制报文
     * @param obj
     * @return
     */
    public String object2HexStr(Object obj) {
        try{
            Map<String, LinkedHashMap<String, String>> map = (Map<String, LinkedHashMap<String, String>>) obj;
            Set<String> keySet = map.keySet();
            Iterator<String> iterator = keySet.iterator();
            // 取出报文命令代码
            String commandCodeKey = iterator.next();
            StringBuffer dataDomainHexSb = new StringBuffer();
            if(StringUtils.isNotBlank(commandCodeKey)){
                if("0x3a".equalsIgnoreCase(commandCodeKey)){
                    // 0107141006020365
//                    String beginHex = "FAF52780AB3A000000000101010000000000000000";
//                    String endHex = "630066000101003F011E00";
                    // 0107141006043633
//                    String beginHex = "FAF52780F23A000000000102000000000000000000";
//                    String endHex = "FFFFFFFFFFFFFFFF";

                    // 青岛公交
//                    String qdBus3a = "FAF54680D93A0000000002050100000000000000000000800C0000000032320000000000000000020000090100000000000000000000800C000000003232000000000000000002000030";
                    String beginHex = "";
                    if("3.4a".equals(CommonFlag.version) || "3.4a1".equals(CommonFlag.version)){
                        beginHex = "FAF52780F23A000000000105000000000000000000";

                    }else {
                        beginHex = "FAF52780F23A000000000102000000000000000000";

                    }


                    String endHex = "FF00FF00FFFFFF53";

                    // 充电状态，决定调用采集返回的充电状态
                    String chargeStatus = "01";
                    // 充电剩余时长
                    String sycdsj = "1700";

                    // 电池总电压1
                    int num = HexUtil.makeRandom(210f, 245f, 0).intValue();
                    String dczdy = HexUtil.random2HexAndReverse(num);
                    // 电池总电流1
                    num = HexUtil.makeRandom(110f, 90f, 0).intValue() + 3200;
                    String dczdl = HexUtil.random2HexAndReverse(num);;
                    // 最高单体电压1
                    num = HexUtil.makeRandom(210f, 245f, 0).intValue();
                    String zgdtdy = HexUtil.random2HexAndReverse(num);
                    // 最低单体电压1
                    num = HexUtil.makeRandom(210f, 245f, 0).intValue();
                    String zddtdy = HexUtil.random2HexAndReverse(num);
                    // 温度测量点最高值1
                    num = HexUtil.makeRandom(40f, 50f, 0).intValue();
                    String wdcldzgz = HexUtil.int2Hex(num);
                    // 温度测量点最低值1
                    num = HexUtil.makeRandom(40f, 50f, 0).intValue();
                    String wdcldzdz = HexUtil.int2Hex(num);
//                    String resultHex = beginHex + "FFFF" + dczdl + zgdtdy + zddtdy + wdcldzgz + wdcldzdz + endHex;
                    String resultHex = beginHex + dczdy + dczdl + zgdtdy + zddtdy + wdcldzgz + wdcldzdz + endHex + chargeStatus + sycdsj;
                    String checkSumDomain = HexUtil.getCheckSumDomain(resultHex.substring(10, resultHex.length()));
                    LOGGER.info("编码完成，发送 " + commandCodeKey + " 报文——msgLog：{}", resultHex + checkSumDomain);
                    return resultHex + checkSumDomain;
                }else {
                    if("0x79".equals(commandCodeKey)){
                        LOGGER.info("编码==" + commandCodeKey );
                    }
                    // 报文数据list
                    LinkedHashMap<String, String> chMap = map.get(commandCodeKey);
                    Set<String> keySet2 = chMap.keySet();
                    Iterator<String> iterator1 = keySet2.iterator();
                    while (iterator1.hasNext()) {
                        if(!ApplicationStartQuartzJobListener.chm.isEmpty()){
                            // 通过命令代码从全局变量中取出对应的字段map
                            LinkedHashMap<String, MsgBean> chmMap = ApplicationStartQuartzJobListener.chm.get(commandCodeKey);
                            // 报文字段
                            String msgField = iterator1.next();
                            // 字段值
                            String msgFieldValue = chMap.get(msgField);
                            // 字段属性实体
                            MsgBean msgBean = chmMap.get(msgField);
                            // 字段类型
                            String fieldType = msgBean.getType();
                            CommandContext commandContext = new CommandContext();
                            MsgFieldTypeStrategy msgFieldTypeStrategy = commandContext.getTypeInstance(fieldType);
                            if(msgFieldTypeStrategy != null){
                                msgFieldValue = msgFieldTypeStrategy.encodeProcess(msgFieldValue);
                            }
                            if("commandCode".equals(msgField)){
                                msgFieldValue = msgFieldValue.substring(2, 4);
                            }
                            if("chargeGunNum".equals(msgField)){
                                msgFieldValue = HeartbeatClient.chargeGunNum;
                            }
                            dataDomainHexSb.append(msgFieldValue);
                        }
                    }
                }
            }
            StringBuffer resultHexMsg = new StringBuffer();
            if("3.4a".equals(CommonFlag.version) || "3.4a1".equals(CommonFlag.version)){
                // 多枪
                dataDomainHexSb = moreChargeGun(commandCodeKey, dataDomainHexSb);
            }
            // 计算校验和域
            String checkSumDomain = HexUtil.getCheckSumDomain(dataDomainHexSb.toString().substring(4, dataDomainHexSb.length()));

            // 版本域+序列号域+数据域+校验和域
            resultHexMsg.append(dataDomainHexSb).append(checkSumDomain).toString();
            // 长度域
            String lengthDomain = Integer.toHexString(resultHexMsg.substring(2, resultHexMsg.length()).length()/2);
            if(lengthDomain.length() < 2){
                lengthDomain = "0" + lengthDomain;
            }
            // 返回起始域+长度域+数据域和校验和域
            String sendMsgStr = (new GetHexMessage().getStartingDomain() + lengthDomain + resultHexMsg).toUpperCase();
            LOGGER.info("编码完成，发送 " + commandCodeKey + " 报文——msgLog：{}", sendMsgStr);
            HexUtil.addSpace(sendMsgStr);
            return sendMsgStr;
        }catch (Exception e){
            LOGGER.error("编码异常：{}", e);
        }
        LOGGER.info("commandCodeKey为空" );
        return "";
    }


    /**
     * 多枪处理
     * @param commandCodeKey
     * @param dataDomainHexSb
     */
    private StringBuffer moreChargeGun(String commandCodeKey, StringBuffer dataDomainHexSb) {
        if(Arrays.asList(MsgTypeConst.COMMAND_CODES).contains(commandCodeKey)){
            // 充电枪数量
            int chargeGunNum = Integer.valueOf(HeartbeatClient.chargeGunNum);
            StringBuffer beforeStr = new StringBuffer();
            // 每个充电枪所有参数
            String chargeGunParams = dataDomainHexSb.substring(18, dataDomainHexSb.length());
            StringBuffer stringBuffer = new StringBuffer();
            // 有枪在进行充电
            if(MsgTypeConst.CHARGE_POSTS.size() > 0){
                for (int i = 0; i < chargeGunNum; i++) {
                    String cpBin = "";
                    String cgpTemp = "";
                    // 如果该枪在充电中
                    if(MsgTypeConst.CHARGE_POSTS.contains("0" + (i + 1))){
                        cpBin = HexUtil.int2Bin(i + 1);
                        cgpTemp = chargeGunParams;
                        // 未充电所有数据都为0
                    }else {
                        cpBin = HexUtil.int2Bin(i+ 1);
                        StringBuffer tempStr = new StringBuffer();
                        for (int k = 0; k < chargeGunParams.length(); k++) {
                            tempStr.append("0");
                        }
                        cgpTemp = tempStr.toString();
                    }
                    //二进制字符串充电类型  并枪模式1
//                    String addCpBin = "1" + cpBin + "01";
                    //单枪模式0
                    String addCpBin = "0" + cpBin + "01";
                    if(!"101".equals(addCpBin)){
                        String chargeTypeHex = HexUtil.bin2Hex(addCpBin);
                        stringBuffer.append(chargeTypeHex).append(cgpTemp);
                    }
                }
            }else {
                String cpBin = "";
                String cgpTemp = "";
                //根据枪的数量进行循环，获取以充电类型开始-->十六进制字符串
                for (int i = 0; i < chargeGunNum; i++) {
                    //二进制枪号字符串
                    cpBin = HexUtil.int2Bin(i + 1);
                    StringBuffer tempStr = new StringBuffer();
                    for (int k = 0; k < chargeGunParams.length(); k++) {
                        tempStr.append("0");
                    }
                    cgpTemp = tempStr.toString();
                    //二进制字符串充电类型  并枪模式1
//                    String addCpBin = "1" + cpBin + "01";
                    //单枪模式0
                    String addCpBin = "0" + cpBin + "01";
                    //充电类型 二进制字符串转为十六进制
                    String chargeTypeHex = HexUtil.bin2Hex(addCpBin);
                    stringBuffer.append(chargeTypeHex).append(cgpTemp);
                }
            }
            beforeStr.append(dataDomainHexSb.substring(0, 16)).append(stringBuffer);
            dataDomainHexSb.delete(0, dataDomainHexSb.length());
            dataDomainHexSb.append(beforeStr);
        }
        return dataDomainHexSb;
    }

}
